﻿// --------------------------------------------------------------------------------------------------------------------- 
// <copyright file="Extensions.cs" company="Scrum for Team System">
//   None
// </copyright>
// <summary>
//   Defines the Extensions type.
// </summary>
// ---------------------------------------------------------------------------------------------------------------------
namespace ScrumForTeamSystem.EventService.TransitionService
{
    using System.Collections.Generic;
    using System.Globalization;
    using System.Linq;
    using System.Text;

    using DataStructures;

    using Microsoft.TeamFoundation.WorkItemTracking.Client;

    using Properties;

    /// <summary>
    /// Defines the Extensions type.
    /// </summary>
    internal static class Extensions
    {
        /// <summary>
        /// Gets the linked items.
        /// </summary>
        /// <param name="workItem">The work item.</param>
        /// <param name="linkTypeName">Name of the link type.</param>
        /// <param name="workItemTypeName">Name of the work item type.</param>
        /// <returns>A collection of linked work items.</returns>
        public static IEnumerable<WorkItem> GetLinkedItems(this WorkItem workItem, string linkTypeName, string workItemTypeName)
        {
            string query;
            return !TryGetQueryString(workItem, linkTypeName, workItemTypeName, out query)
                           ? new WorkItem[] { }
                           : workItem.Store.Query(query).OfType<WorkItem>();
        }

        /// <summary>
        /// Gets the linked items.
        /// </summary>
        /// <param name="workItem">The work item.</param>
        /// <param name="linkTypeName">Name of the link type.</param>
        /// <param name="workItemTypeName">Name of the work item type.</param>
        /// <param name="excludedStates">The excluded states.</param>
        /// <returns>A collection of linked work items.</returns>
        public static IEnumerable<WorkItem> GetLinkedItems(this WorkItem workItem, string linkTypeName, string workItemTypeName, IEnumerable<string> excludedStates)
        {
            string query;

            if (!TryGetQueryString(workItem, linkTypeName, workItemTypeName, out query))
            {
                return new WorkItem[] { };
            }

            if (excludedStates != null && excludedStates.Count() != 0)
            {
                var concatStates = string.Empty;
                foreach (var excludedState in excludedStates)
                {
                    concatStates = string.Concat(concatStates, string.IsNullOrEmpty(concatStates) ? string.Empty : ",", "'", excludedState, "'");
                }

                query = string.Concat(
                        query,
                        string.Format(CultureInfo.InvariantCulture, Settings.Default.ExludedStateFilter, concatStates));
            }

            return workItem.Store.Query(query).OfType<WorkItem>();
        }

        /// <summary>
        /// Tries the get the query string. Returns <c>false</c> if no linked ids found.
        /// </summary>
        /// <param name="workItem">The work item.</param>
        /// <param name="linkTypeName">Name of the link type.</param>
        /// <param name="workItemTypeName">Name of the work item type.</param>
        /// <param name="query">The query.</param>
        /// <returns>
        /// <c>True</c> if the work item has linked work items; otherwise <c>false</c>.
        /// </returns>
        private static bool TryGetQueryString(WorkItem workItem, string linkTypeName, string workItemTypeName, out string query)
        {
            var relatedLinksIds =
                    workItem.Links.OfType<RelatedLink>().Where(
                            rl =>
                            rl.LinkTypeEnd.LinkType.ReferenceName.Equals(linkTypeName))
                            .Select(rl => rl.RelatedWorkItemId).ToArray();

            if (relatedLinksIds.Count() == 0)
            {
                query = null;
                return false;
            }

            var concatIds = string.Empty;
            foreach (var id in relatedLinksIds)
            {
                concatIds = string.Concat(concatIds, string.IsNullOrEmpty(concatIds) ? string.Empty : ",", id);
            }

            query = string.Format(
                    CultureInfo.InvariantCulture,
                    Settings.Default.LinkedItemsQuery,
                    concatIds,
                    workItemTypeName);

            return true;
        }
    }
}
